package com.ldy.letcode;

import com.google.common.base.Splitter;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <br>
 * 版权: Copyright (c) 2011-2018<br>
 * 公司: 活力天汇<br>
 *
 * @author: 刘德咏<br>
 * @date: 2018-04-19<br>
 */
public class LetCode {

    /**
     * Given nums = [2, 7, 11, 15], target = 9,

         Because nums[0] + nums[1] = 2 + 7 = 9,
         return [0, 1].
     * @param target
     * @return
     */
    public int[] letCode1(int[] nums, int target) {
        HashMap<Integer, Integer> valueToKey = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            valueToKey.put(nums[i], i);
            int key = target - nums[i];
            if (valueToKey.containsKey(key))
                return new int[]{valueToKey.get(key), i};
        }
        return new int[]{};
    }

    /**
     * 进行Z字变换
     * @param str
     * @param numberRow
     */
    public void letCode6(String str, int numberRow) {
        // 计算二维数组的列
        if (StringUtils.isBlank(str) || numberRow <= 0) {
            return;
        }
        if (numberRow == 1) {
            System.out.println(str);
            return;
        }
        int length = str.length();
        int base = length / (numberRow * 2 - 2);
        int extra = length % (numberRow * 2 - 2);
        int column = base * (numberRow - 1) + extra / numberRow + extra % numberRow;
        int[][] result  = new int[numberRow][column];
        for (int j=0; j < numberRow; j ++) {
            for (int i=0; i<column; i++) {
                result[i][j] = 1;
            }
        }
    }

    /**
     * 进行Z字变换
     * @param str
     * @param numberRow
     */
    public char[][] letCode6V2(String str, int numberRow) {
        // 第一步 对str进行 2*numberRow 进行定长切分
        // 第二步 把切分好的每个单个处理成二维数组
        // 第三步 按行合并所有的二维数组。

        // 计算二维数组的列
        if (StringUtils.isBlank(str) || numberRow <= 0) {
            return null;
        }
        if (numberRow == 1) {
            System.out.println(str);
            return null;
        }
        StringBuilder sb = new StringBuilder();
        List<char[][]> listChar = new ArrayList<>();
        Splitter.fixedLength(2 * numberRow - 2).split(str).forEach(splitStr -> {
            // 给最后一列补空格
            if (splitStr.length() < 2 * numberRow - 2) {
                // %1$-34s 补到34 长度
                String formatKey = "%1$-" + String.valueOf(2 * numberRow - 2) + "s";
                splitStr = String.format(formatKey, splitStr);
            }
            listChar.add(dealTowLngArrFromFixLengthString(splitStr, numberRow));
        });
        // 合并二维数组
        char[][] result = mergeTwoLngByLine(numberRow, listChar);
        return result;
    }

    /**
     * 将字符串按照 二维数组的行数，处理为二维数组
     * @param splitStr
     * @param numberRow
     * @return
     */
    private char[][] dealTowLngArrFromFixLengthString(String splitStr, int numberRow) {
        char[][] result = new char[numberRow][numberRow - 1];
        char[] charArr = splitStr.toCharArray();
        int singleAtomLength = charArr.length;
        // 用来定位列的索引
        int j = 0;
        for ( int i = 0; i < singleAtomLength; i++) {
            if (i < numberRow) {
                result[i][0] = charArr[i];
            } else {
                result[numberRow - 1 - ++j][i + 1 - numberRow] = charArr[i];
            }
        }
        // 设置结果中 不为 ' '的字符，变为 ' '
        for (int m=0; m < numberRow ; m++) {
            for (int n=0; n < numberRow -1; n++) {
                if (result[m][n] == '\u0000')
                    result[m][n] = ' ';
            }
        }
        return result;
    }

    /**
     * 二维数组合并
     * @param numberRow
     * @param listChar
     * @return
     */
    public char[][] mergeTwoLngByLine(int numberRow, List<char[][]> listChar) {
        // 前面所有的满切割、最后一个array可能不满，不满全部为空格
        int column = listChar.size() * (numberRow - 1);

        char[][] result = new char[numberRow][column];
        for (int i = 0; i < listChar.size(); i++) {
            char[][] tempCharArr = listChar.get(i);
            for (int m = 0; m < tempCharArr.length; m++) {
                for (int n=0; n < numberRow - 1; n++) {
                    result[m][(numberRow - 1) * i + n] = tempCharArr[m][n];
                }
            }
        }
        return result;
    }

    /**
     * 打印二维数组
     * @param arr
     * @return
     */
    public void pringTowLngArr(char[][] arr) {
        for (int i =0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j]);
            }
            System.out.println();
        }
    }

    /**
     * 反转整数
     * @param num
     * @return
     */
    public int letCode7(int num) {
        // 0 代表正， 1代表负
        int flag = 0;
        if (num < 0) {
            num = Math.abs(num);
            flag = 1;
        }
        if (num == 0) {
            return 0;
        }
        String resultNum = "";
        while (num != 0) {
            resultNum += num % 10;
            num = num / 10;
        }
        Integer result = Integer.parseInt(resultNum);
        return flag == 1 ? -result : result;
    }

    /**
     * 将字符串转为整数
     * @param str
     * @return
     */
    public int letCode8(String str) {
        char[] chars = str.toCharArray();
        int index1 = -1;
        int index2 = -1;
        char temp;
        /** 0代表正，1代表负*/
        int flag = 0;
        String tempResult = "";
        for (int i = 0; i < chars.length; i++) {
            temp = chars[i];
            if (index1 < 0) {
                if (temp == ' ') {
                    continue;
                } else if (temp > '0' && temp < '9' || temp == '-') {
                    index1 = i;
                    continue;
                } else {
                    // 第一位非符号位、数字,空格
                    return 0;
                }
            }
            if (index1 > -1 && (temp < '0' || temp > '9')) {
                index2 = i;
            }
            if (index1 > -1 && index2 == -1 && i == chars.length - 1) {
                index2 = chars.length;
            }
            if (index1 > -1 && index2 > -1) {
                tempResult = str.substring(index1, index2);
                break;
            }
        }
        if (tempResult.substring(0, 1).equals("-")) {
            flag = 1;
            tempResult = tempResult.substring(1);
        }
        if (tempResult.length() > 11) {
            return flag == 1 ? Integer.MIN_VALUE : Integer.MAX_VALUE;
        }
        return flag == 1 ? -Integer.parseInt(tempResult) : Integer.parseInt(tempResult);
    }

    /**
     * 验证一个正式是否是回文数，不能转化为string 来处理
     * @param num
     * @return
     */
    public boolean letCode9(int num) {
        if (num <= 0) {
            return false;
        }
        int orignNum = num;
        String resultNum = "";
        while (num != 0) {
            resultNum += num % 10;
            num = num / 10;
        }
        return Integer.parseInt(resultNum) == orignNum;
    }
//
//    给定 n 个非负整数 a1，a2，...，an，每个数代表坐标中的一个点 (i, ai) 。画 n 条垂直线，使得垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线，使得它们与 x 轴共同构成的容器可以容纳最多的水。
//
//    注意：你不能倾斜容器，n 至少是2。
    public int maxArea(int[] height) {
        if (height.length < 2) {
            return 0;
        }
        // 存储所有的结果 i_j_area
        List<String> result = new ArrayList<>();
        String tempArea;
        for (int i = 0; i < height.length; i++) {
            for (int j = i + 1 ; j< height.length; j++) {
                result.add(i + "_" + j + "_" + (height[i] + height[j]) * (j - i) / 2);
            }
        }
        // 比出result中area最大的一项
        String maxAreaString = result.stream().max(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return Integer.parseInt(o1.substring(o1.lastIndexOf("_"))) - Integer.parseInt(o2.substring(o2.lastIndexOf("_")));
            }
        }).get();
        System.out.println(maxAreaString);
        return 0;
    }

    @Test
    public void testLetCode6() {
        String str = "abcdefghijklmn";
        char[][] chars = letCode6V2(str, 4);
        pringTowLngArr(chars);
    }

    @Test
    public void testLetCode7() {
        System.out.println(letCode7(-123));
        System.out.println(letCode7(123));
        System.out.println(letCode7(0));
        System.out.println(letCode7(1));
    }

    @Test
    public void testLetCode8() {
        System.out.println(letCode8("42"));
        System.out.println(letCode8("    -42"));
        System.out.println(letCode8("4193 with words"));
        System.out.println(letCode8("word and 987"));

    }
    @Test
    public void testLetCode9() {
        System.out.println(letCode9(-1));
        System.out.println(letCode9(0));
        System.out.println(letCode9(1));
        System.out.println(letCode9(121));
    }

    /**
     * Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
     Output: 7 -> 0 -> 8
     Explanation: 342 + 465 = 807.
     */
    public class ListNode {
        int val;
        ListNode next;
        ListNode(int x) {
            val= x;
        }

        public void addTo(ListNode parentNode) {
            while (parentNode.next != null) {
                parentNode = parentNode.next;
            }
            parentNode.next = this;
        }
    }

    /**
     * 实现翻转需求。
     * @param l1
     * @param l2
     * @return
     */
    public ListNode twoNumberAdd(ListNode l1, ListNode l2) {
        ListNode l3 = new ListNode(0);
        while (l1 != null && l2 != null) {
            ListNode l3_temp = new ListNode(l1.val + l2.val);
            l3_temp.addTo(l3);
            l1 = l1.next;
            l2 = l2.next;
        }

        ListNode head = new ListNode(0);
        l3 = l3.next;
        while (l3 != null) {
            ListNode l1Temp = new ListNode(l3.val);
            ListNode reserveNode = head.next;
            l1Temp.next = reserveNode;
            head.next = l1Temp;
            l3 = l3.next;
        }

        ListNode target = new ListNode(0);
        head = head.next;
        while (head != null) {
            ListNode headTemp;
            if (head.val > 9) {
                headTemp = new ListNode(head.val - 10);
                if (head.next == null) {
                    head.next = new ListNode(1);
                } else {
                    head.next.val += 1;
                }
            } else {
                headTemp = new ListNode(head.val);
            }
            ListNode jinwei = target.next;
            headTemp.next = jinwei;
            target.next = headTemp;
            head = head.next;
        }
        return target.next;
    }

    public ListNode twoNumberAddV2(ListNode l1, ListNode l2) {
        ListNode l3 = new ListNode(0);
        // 进位标识
        Integer sign = 0;
        while (l1 != null && l2 != null) {
            int totalVal = l1.val + l2.val;
            ListNode l3_temp = new ListNode(totalVal % 10 + sign);
            sign = totalVal / 10;
            l3_temp.addTo(l3);
            l1 = l1.next;
            l2 = l2.next;
        }
        if (sign > 0) {
            ListNode l3_temp = new ListNode(sign);
            l3_temp.addTo(l3);
        }
        return l3.next;
    }


    private String string(ListNode target) {
        StringBuilder sb = new StringBuilder();
        while (target != null) {
            sb.append("ListNode{val=").append(target.val).append("}").append(",");
            target = target.next;
        }
        return sb.substring(0, sb.length() - 1);
    }
    @Test
    public void test1() throws Exception{
        int[] nums = new int[]{2,7,11,15};
        System.out.println(Arrays.toString(letCode1(nums, 18)));
    }

    @Test
    public void test2() throws Exception {
        ListNode l1 = new ListNode(2);
        ListNode l1_1 = new ListNode(4);
        ListNode l1_2 = new ListNode(7);
        l1.next = l1_1;
        l1_1.next = l1_2;


        ListNode l2 = new ListNode(5);
        ListNode l2_1 = new ListNode(6);
        ListNode l2_2 = new ListNode(4);
        l2.next = l2_1;
        l2_1.next = l2_2;

        System.out.println(string(twoNumberAddV2(l1, l2)));

    }


}